home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / URL Helper II / Source / Exceptions.h < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-20  |  25.2 KB  |  883 lines  |  [TEXT/MMCC]

  1.  
  2. /*********************************************************************
  3.  
  4. FILENAME
  5.     Exceptions.h
  6.     
  7. DESCRIPTION
  8.     A collection of routines and macros to handle assertions and
  9.     exceptions.
  10.  
  11. COPYRIGHT
  12.     Copyright © Apple Computer, Inc. 1989-1991
  13.     All rights reserved.
  14.  
  15. ROUTINES
  16.     EXTERNALS
  17.         dprintf
  18.         check_dprintf
  19.         checkpos_dprintf
  20.  
  21. MACROS
  22.     EXTERNALS
  23.         check
  24.         ncheck
  25.         check_action
  26.         ncheck_action
  27.         require
  28.         nrequire
  29.         require_action
  30.         nrequire_action
  31.         resume
  32.  
  33. MODIFICATION HISTORY
  34.     08/03/89    Sean Parent
  35.         1)    Version 1.0d1 started
  36.     09/26/89    sp
  37.         1)    Corrected the description of require
  38.     12/08/89    sp
  39.         1)    Ported from XXXX Exceptions.h
  40.     03/16/90    sp
  41.         1)    Removed refCon parameter
  42.         2)    Added the "n" calls
  43.     05/10/90    sp
  44.         1)    Added the dprintf call and revved other macros to use it.
  45.     06/12/90    sp
  46.         1)    Modified the dprint off to use a macro for traceOption.
  47.     08/01/90    sp
  48.         1)    Modified for C++ compatibility (Thanks Ron).
  49.     08/14/90    sp
  50.         1)    Added action calls.
  51.     09/20/90    sp
  52.         1)    Removed rescue_ prefix in require exception labels.
  53.     01/16/91    sp
  54.         1)    Fixed some comments and updated the copyright notice.
  55.     02/13/91    sp
  56.         1)    Added check_action and ncheck_action calls.
  57.         2)    Added SetExceptionOption
  58.     02/22/91    sp
  59.         1)    Added {} around all macros just to be defensive for TED.
  60.         2)    Put everything in "if (true) { MACRO } else" form to be very
  61.             defensive.
  62.     02/26/91    sp
  63.         1)    Added a null statement after the else of each macro for the
  64.             fools who forgot to put ; in.
  65.     03/13/91    sp
  66.         1)    Added void* cast for privateAssertion for C++.
  67.     03/13/91    sp/NB
  68.         1)    Fixed void* cast for privateAssertion for C++.
  69.     11/04/91    sp
  70.         1)    Removed retry.
  71.         2)    Added DEBUGMIN support.
  72.         3) Removed SetExceptionOption.
  73.         4) Cleaned up for Develop article.
  74.     11/05/91    sp
  75.         1)    Removed PlaceHolder() and moved to "do { MACRO } while(false)"
  76.     11/19/91 sp
  77.         1)    Added DEBUGSYM level.
  78.         
  79. NOTE
  80.     To keep code size down, use these routines and macros with the C
  81.     compiler option -b2 or -b3. This will eliminate duplicate strings
  82.     within a procedure.
  83.  
  84. *********************************************************************/
  85.  
  86. #ifndef __EXCEPTIONS__
  87. #define __EXCEPTIONS__
  88.  
  89. /*********************************************************************
  90.  
  91. INCLUDES
  92.  
  93. *********************************************************************/
  94.  
  95. #ifndef    __TYPES__
  96. #include    <Types.h>
  97. #endif
  98.  
  99. /*<FF>*/
  100. /*********************************************************************
  101.  
  102. CONSTANTS AND CONTROL
  103.  
  104. *********************************************************************/
  105.  
  106. /*
  107.     These defines are used to control the amount of information
  108.     displayed when an assertion fails. DEBUGOFF and WARN will run
  109.     silently. MIN will simply break into the debugger. ON will break
  110.     and display the assertion that failed and the exception (for
  111.     require statements). FULL will also display the source file name
  112.     and line number. SYM does a SysBreak and is usefull when using a
  113.     symbolic debugger like SourceBug or SADE. They should be set into
  114.     DEBUGLEVEL. The default LEVEL is OFF.
  115. */
  116.  
  117. #define DEBUGOFF        0
  118. #define DEBUGWARN        1
  119. #define DEBUGMIN        2
  120. #define DEBUGON        3
  121. #define DEBUGFULL        4
  122. #define DEBUGSYM        6
  123. /*
  124. #ifndef    DEBUGLEVEL
  125. #define    DEBUGLEVEL    DEBUGOFF
  126. #endif    DEBUGLEVEL
  127. */
  128. /*
  129.     resumeLabel is used to control the insertion of labels for use with
  130.     the resume macro. If you do not use the resume macro and you wish
  131.     to have multible exceptions per label then you can add the
  132.     following define to you source code.
  133.     
  134.     #define resumeLabel(exception)
  135. */
  136.  
  137. #define resumeLabel(exception)    resume_ ## exception:
  138.  
  139. /*
  140.     trace and notrace are used for the traceOption for dprintf. If
  141.     trace is used then the actual behavior can be controled from
  142.     Macsbug. The macros in Macsbug are traceGo and traceBreak. traceGo
  143.     is the default and execution will continue after the break. If
  144.     traceBreak is used then execution will halt.
  145. */
  146.  
  147. #define    trace        "\p;dprintf;doTrace"
  148. #define    notrace    "\p;dprintf"
  149.  
  150. /*
  151.     traceon and debugon are used to test for options
  152. */
  153.  
  154. #define    traceon    ((DEBUGLEVEL > DEBUGWARN) && defined(TRACEON))
  155. #define    debugon    (DEBUGLEVEL > DEBUGWARN)
  156.  
  157. /*
  158.     Add some macros for DEBUGMIN and DEBUGSYM to keep the size down.
  159. */
  160.  
  161. #define    __DEBUGSMALL    ((DEBUGLEVEL == DEBUGMIN) ||            \
  162.                                  (DEBUGLEVEL == DEBUGSYM))
  163.  
  164. #if    DEBUGLEVEL == DEBUGMIN
  165. #define    __DebuggerBreak    Debugger()
  166. #elif    DEBUGLEVEL == DEBUGSYM
  167. #define  __DebuggerBreak    SysBreak()
  168. #endif
  169.  
  170. /*<FF>*/
  171. /*********************************************************************
  172.  
  173. ROUTINE
  174.     void dprintf(traceOption, format, ...)
  175.  
  176. DESCRIPTION
  177.     dprintf is used like printf only the information is displayed in
  178.     MacsBug. traceOption is used to specify whether the execution
  179.     should continue after the break or not. format contains
  180.     two types of objects: ordinary characters, which are displayed in
  181.     Macsbug, and coversion specifications, each of which causes
  182.     conversion and printing of the next successive argument to dprintf.
  183.     Each conversion specification begins with a % and ends with a
  184.     conversion character. Between % and the conversion character there
  185.     may be, in order:
  186.     
  187.     •    Zero or more flag characters, which modify the meaning of the
  188.         conversion specification.
  189.     •    A number that specifies the minimum field width. The converted
  190.         argument will be printed in a field at least this wide. If
  191.         necessary it will be padded on the left (or right, if left
  192.         adjustment is called for) to make up the field width.
  193.     •    A period, which separates the field width from the precision.
  194.     •    A number, the precision, that specifies the maximum number of
  195.         characters to be printed from a string, or the number of digits
  196.         after the decimal point of a floatingpoint value, or the minimum
  197.         number of digits for an integer.
  198.     •    An h if the integer is to be printed as a short, or l if as
  199.         long (ignored since int is long), or L to specify that the
  200.         following e, E, f, g, or G conversion is a long double.
  201.     
  202.     Note: A field width or precision may be indicated by an * instead
  203.     of a digit string. In this case, an integer arg parameter supplies
  204.     the field width or precision. The arg parameter that is actually
  205.     converted is not fetched until the conversion letter is seen;
  206.     therefore, the arg paramters specifying field width or precision
  207.     must appear immediately before the arg parameter (if any) to be
  208.     converted.
  209.     
  210.     The flag characters are:
  211.     
  212.         -        The result of the conversion will be left justified
  213.                 within the field.
  214.         +        The result of a signed conversion always begins with a
  215.                 sign (+ or -).
  216.         space    If the first character of a signed conversion is not a
  217.                 sign, a space will be prefixed to the result. This implies
  218.                 that if the space and + flags both appear, the space flag
  219.                 will be ignored.
  220.         #        The value is to be converted to an alternate form. For c,
  221.                 d, s, and u conversions, the flag has no effect. For o
  222.                 conversions, it increases the precision to force the first
  223.                 digit of the result to be zero. For x, and X conversions,
  224.                 a nonzero result will have 0x or 0X prefixed to it. For
  225.                 e, E, f, g, and G conversions, the result will always
  226.                 contain a decimal point, even if no digits follow the
  227.                 point. For g and G conversion, trailing zeros in the
  228.                 fractional part will not be removed from the result.
  229.         0        The 0 flag pads the field with zeros on the left only;
  230.                 this applies to d, i, o, u, x, X, e, E, f, g, and G
  231.                 conversions. The leading zeros pad the field width, and
  232.                 no space padding is performed. If both the 0 and - flags
  233.                 appear, the 0 flag is ignored. If a precision is specified
  234.                 for d, i, o, u, x, and X conversions, the 0 flag is
  235.                 ignored.
  236.     
  237.     The standard conversions are:
  238.     
  239.         d,i    int            Decimal number.
  240.         o        int            Unsigned octal number (w/o a leading zero).
  241.         x,X    int            Unsigned hexadecimal number (w/o a leading 0x
  242.                                 or oX), using abcdef or ABCDEF for 10,…,15.
  243.         u        int            Unsigned decimal number.
  244.         c        int            Single character.
  245.         s        char*            C string.
  246.         f        double        [-]m.dddddd, where the number of d's is given
  247.                                 by the precision (default 6).
  248.         e,E    double        [-]m.dddddde±xx or [-]m.ddddddE±xx, where the
  249.                                 number of d's is given by the precision
  250.                                 (default 6).
  251.         g,G    double        Use %e or %E if the exponent is less than -4
  252.                                 or greater than or equal to the precision;
  253.                                 otherwise use %f. Trailing zeros and a
  254.                                 trailing decimal point are not printed.
  255.         p        void*            Pointer.
  256.         %                        No argument is converted; print a %.
  257.     
  258.     The supported MPW extensions are:
  259.     
  260.         P        StringPtr    Pascal string.
  261.     
  262.     Of the MPW printf convertion characters only "n" is not supported.
  263.     In addition to the standard characters, the following are defined:
  264.     
  265.         b        Boolean        Outputs either true or false.
  266.         j        Point            Used like the d option.
  267.         J        point*        Fixed point. Used like the f option.
  268.         F        Fixed            Used like the f option.
  269.         T        Fract            Used like the f option.
  270.         r        Rect*            Displays the rect with each piece seperated by
  271.                                 ", ". Used like the d option.
  272.         R        rectangle*    Similar to r but for fixed point rectangles.
  273.                                 Used like the f option.
  274.         M        mapping.        Displays the mapping seperated by ", " and
  275.                                 "\n". The third column is displayed as fract.
  276.                                 Used like the f option.
  277.     
  278.         
  279.     dprintf requires that the MacsBug dcmd dprintf is present.
  280.     
  281.     Characters used:     bcdefghij l nop rs u  x
  282.                                 EFG  J LM  P R T   X
  283.     Not used:            a         k m   q  t vw yz
  284.                             ABCD   HI K  NO Q S UVW YZ
  285.     
  286.     See the MPW C Reference for more information on printf.
  287.  
  288. Echo "                                                            ∂n∂
  289.     PRINT            OFF,NOHDR                                    ∂n∂
  290.     INCLUDE        'Traps.a'                                    ∂n∂
  291.     PRINT            ON                                                ∂n∂
  292.     PROC                                                            ∂n∂
  293.     _DebugStr                                                    ∂n∂
  294.     SUBQ            #4,SP        ; Fix the stack                ∂n∂
  295.     ENDPROC                                                        ∂n∂
  296.     END                                                            ∂n∂
  297. " | Asm -l
  298.  
  299. *********************************************************************/
  300.  
  301. void dprintf(StringPtr, char[], ...)
  302.     = { 0xABFF, 0x594F };
  303.  
  304. /*<FF>*/
  305. /*********************************************************************
  306.  
  307. ROUTINE
  308.     void* check_dprintf(assertion, traceOption, format, ...)
  309.  
  310. DESCRIPTION
  311.     If assertion is non-zero then assertion is returned. Otherwise the
  312.     dprintf is invoked and zero is returned.
  313.     
  314. Echo "                                                            ∂n∂
  315.     PRINT            OFF,NOHDR                                    ∂n∂
  316.     INCLUDE        'Traps.a'                                    ∂n∂
  317.     PRINT            ON                                                ∂n∂
  318.     PROC                                                            ∂n∂
  319.     MOVE.L        (SP)+,D0    ; Pop value into D0            ∂n∂
  320.     BNE.S            @1            ; If !0 then branch            ∂n∂
  321.     _DebugStr                                                    ∂n∂
  322.     SUBQ            #4,SP        ; Fix the stack                ∂n∂
  323.     CLR.W            D0            ; Result is zero                ∂n∂
  324. @1    SUBQ            #4,SP        ; Fix stack for pop            ∂n∂
  325.     ENDPROC                                                        ∂n∂
  326.     END                                                            ∂n∂
  327. " | Asm -l
  328.     
  329. *********************************************************************/
  330.     
  331. void* check_dprintf(void*, StringPtr, char[], ...) =
  332.     { 0x201F, 0x6606, 0xABFF, 0x594F, 0x4240, 0x594F };
  333.     
  334. /*<FF>*/
  335. /*********************************************************************
  336.  
  337. ROUTINE
  338.     void* checkpos_dprintf(assertion, traceOption, format, ...)
  339.  
  340. DESCRIPTION
  341.     If assertion is positive then assertion is returned. Otherwise the
  342.     dprintf is invoked and zero is returned.
  343.     
  344. Echo "                                                            ∂n∂
  345.     PRINT            OFF,NOHDR                                    ∂n∂
  346.     INCLUDE        'Traps.a'                                    ∂n∂
  347.     PRINT            ON                                                ∂n∂
  348.     PROC                                                            ∂n∂
  349.     MOVE.L        (SP)+,D0    ; Pop value into D0            ∂n∂
  350.     BGE.S            @1            ; If >= 0 then branch        ∂n∂
  351.     _DebugStr                                                    ∂n∂
  352.     SUBQ            #4,SP        ; Fix the stack                ∂n∂
  353.     CLR.W            D0            ; Result is zero                ∂n∂
  354. @1    SUBQ            #4,SP        ; Fix stack for pop            ∂n∂
  355.     ENDPROC                                                        ∂n∂
  356.     END                                                            ∂n∂
  357. " | Asm -l
  358.     
  359. *********************************************************************/
  360.     
  361. void* checkpos_dprintf(void*, StringPtr, char[], ...) =
  362.     { 0x201F, 0x6C06, 0xABFF, 0x594F, 0x4240, 0x594F };
  363.  
  364. /*<FF>*/
  365. /*********************************************************************
  366.  
  367. MACRO
  368.     check(assertion)
  369.  
  370. DESCRIPTION
  371.     If debugging is on then check will test assertion and if it fails
  372.     break into the debugger. Otherwise check does nothing.
  373.  
  374. *********************************************************************/
  375.  
  376. #if    __DEBUGSMALL
  377.  
  378. #define check(assertion)                                                            \
  379.     do {                                                                                    \
  380.         if (assertion) ;                                                                \
  381.         else __DebuggerBreak;                                                        \
  382.     } while (false)
  383.  
  384. #elif    DEBUGLEVEL == DEBUGON
  385.  
  386. #define check(assertion)                                                            \
  387.     do {                                                                                    \
  388.         if (assertion) ;                                                                \
  389.         else {                                                                            \
  390.             dprintf(notrace, "Assertion \"%s\" Failed",    #assertion);    \
  391.         }                                                                                    \
  392.     } while (false)
  393.  
  394. #elif    DEBUGLEVEL == DEBUGFULL
  395.  
  396. #define check(assertion)                                                            \
  397.     do {                                                                                    \
  398.         if (assertion) ;                                                                \
  399.         else {                                                                            \
  400.             dprintf(notrace,    "Assertion \"%s\" Failed\n"                    \
  401.                                     "File: %s\n"                                        \
  402.                                     "Line: %d",                                            \
  403.                 #assertion, __FILE__, __LINE__);                                    \
  404.         }                                                                                    \
  405.     } while (false)
  406.     
  407. #else
  408.  
  409. #define check(assertion)
  410.  
  411. #endif
  412.  
  413. /*<FF>*/
  414. /*********************************************************************
  415.  
  416. MACRO
  417.     ncheck(assertion)
  418.  
  419. DESCRIPTION
  420.     If debugging is on then ncheck will test !assertion and if it fails
  421.     break into the debugger. Otherwise ncheck does nothing.
  422.  
  423. *********************************************************************/
  424.  
  425. #if    __DEBUGSMALL
  426.  
  427. #define ncheck(assertion)                                                            \
  428.     do {                                                                                    \
  429.         if (assertion) __DebuggerBreak;                                            \
  430.     } while (false)
  431.  
  432. #elif    DEBUGLEVEL == DEBUGON
  433.  
  434. #define ncheck(assertion)                                                            \
  435.     do {                                                                                    \
  436.         void*    __privateAssertion    = (void*)(assertion);                    \
  437.                                                                                             \
  438.         if (__privateAssertion) {                                                    \
  439.             dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed",        \
  440.                 #assertion, __privateAssertion);                                    \
  441.         }                                                                                    \
  442.     } while (false)
  443.  
  444. #elif    DEBUGLEVEL == DEBUGFULL
  445.  
  446. #define ncheck(assertion)                                                            \
  447.     do {                                                                                    \
  448.         void*    __privateAssertion    = (void*)(assertion);                    \
  449.                                                                                             \
  450.         if (__privateAssertion) {                                                    \
  451.             dprintf(notrace,    "Assertion \"!(%s [= %#08X])\" Failed\n"    \
  452.                                     "File: %s\n"                                        \
  453.                                     "Line: %d",                                            \
  454.             #assertion, __privateAssertion, __FILE__, __LINE__);            \
  455.         }                                                                                    \
  456.     } while (false)
  457.  
  458. #else
  459.  
  460. #define ncheck(assertion)
  461.  
  462. #endif
  463.  
  464. /*<FF>*/
  465. /*********************************************************************
  466.  
  467. MACRO
  468.     check_action(assertion, action)
  469.  
  470. DESCRIPTION
  471.     If debugging is on then check_action will test assertion and if it
  472.     fails break into the debugger then execute action. Otherwise
  473.     check_action does nothing.
  474.     
  475. *********************************************************************/
  476.  
  477. #if    __DEBUGSMALL
  478.  
  479. #define check_action(assertion, action)                                        \
  480.     do {                                                                                    \
  481.         if (assertion) ;                                                                \
  482.         else {                                                                            \
  483.             __DebuggerBreak;                                                            \
  484.             { action }                                                                    \
  485.     } while (false)
  486.  
  487. #elif    DEBUGLEVEL == DEBUGON
  488.  
  489. #define check_action(assertion, action)                                        \
  490.     do {                                                                                    \
  491.         if (assertion) ;                                                                \
  492.         else {                                                                            \
  493.             dprintf(notrace, "Assertion \"%s\" Failed",    #assertion);    \
  494.             { action }                                                                    \
  495.         }                                                                                    \
  496.     } while (false)
  497.  
  498. #elif    DEBUGLEVEL == DEBUGFULL
  499.  
  500. #define check_action(assertion, action)                                        \
  501.     do {                                                                                    \
  502.         if (assertion) ;                                                                \
  503.         else {                                                                            \
  504.             dprintf(notrace,    "Assertion \"%s\" Failed\n"                    \
  505.                                     "File: %s\n"                                        \
  506.                                     "Line: %d",                                            \
  507.                 #assertion, __FILE__, __LINE__);                                    \
  508.             { action }                                                                    \
  509.         }                                                                                    \
  510.     } while (false)
  511.  
  512. #else
  513.  
  514. #define check_action(assertion, action)
  515.  
  516. #endif
  517.  
  518. /*<FF>*/
  519. /**************************************************************************************
  520.  
  521. MACRO
  522.     ncheck_action(assertion, action)
  523.  
  524. DESCRIPTION
  525.     If debugging is on then ncheck_action will test !assertion and if
  526.     it fails break into the debugger then execute action. Otherwise
  527.     ncheck_action does nothing.
  528.  
  529. *********************************************************************/
  530.  
  531. #if    __DEBUGSMALL
  532.  
  533. #define ncheck_action(assertion, action)                                        \
  534.     do {                                                                                    \
  535.         if (assertion) {                                                                \
  536.             __DebuggerBreak;                                                            \
  537.             { action }                                                                    \
  538.         }                                                                                    \
  539.     } while (false)
  540.  
  541. #elif    DEBUGLEVEL == DEBUGON
  542.  
  543. #define ncheck_action(assertion, action)                                        \
  544.     do {                                                                                    \
  545.         void*    __privateAssertion    = (void*)(assertion);                    \
  546.                                                                                             \
  547.         if (__privateAssertion) {                                                    \
  548.             dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed",        \
  549.                 #assertion, __privateAssertion);                                    \
  550.             { action }                                                                    \
  551.         }                                                                                    \
  552.     } while (false)
  553.  
  554. #elif DEBUGLEVEL == DEBUGFULL
  555.  
  556. #define ncheck_action(assertion, action)                                        \
  557.     do {                                                                                    \
  558.         void*    __privateAssertion    = (void*)(assertion);                    \
  559.                                                                                             \
  560.         if (__privateAssertion) {                                                    \
  561.             dprintf(notrace,    "Assertion \"!(%s [= %#08X])\" Failed\n"    \
  562.                                     "File: %s\n"                                        \
  563.                                     "Line: %d",                                            \
  564.             #assertion, __privateAssertion, __FILE__, __LINE__);            \
  565.             { action }                                                                    \
  566.         }                                                                                    \
  567.     } while (false)
  568.  
  569. #else
  570.  
  571. #define ncheck_action(assertion, action)
  572.  
  573. #endif
  574.  
  575. /*<FF>*/
  576. /*********************************************************************
  577.  
  578. MACRO
  579.     require(assertion, exception)
  580.  
  581. DESCRIPTION
  582.     require will test assertion and if it fails:
  583.         break into the debugger if debugging is on.
  584.         goto exception.
  585.  
  586. *********************************************************************/
  587.  
  588. #if    __DEBUGSMALL
  589.  
  590. #define require(assertion, exception)                                            \
  591.     do {                                                                                    \
  592.         if (assertion) ;                                                                \
  593.         else {                                                                            \
  594.             __DebuggerBreak;                                                            \
  595.             goto exception;                                                            \
  596.             resumeLabel(exception);                                                    \
  597.         }                                                                                    \
  598.     } while (false)
  599.  
  600. #elif    DEBUGLEVEL == DEBUGON
  601.  
  602. #define require(assertion, exception)                                            \
  603.     do {                                                                                    \
  604.         if (assertion) ;                                                                \
  605.         else {                                                                            \
  606.             dprintf(notrace,    "Assertion \"%s\" Failed\n"                    \
  607.                                     "Exception \"%s\" Raised",                        \
  608.             #assertion, #exception);                                                \
  609.             goto exception;                                                            \
  610.             resumeLabel(exception);                                                    \
  611.         }                                                                                    \
  612.     } while (false)
  613.  
  614. #elif DEBUGLEVEL == DEBUGFULL
  615.  
  616. #define require(assertion, exception)                                            \
  617.     do {                                                                                    \
  618.         if (assertion) ;                                                                \
  619.         else {                                                                            \
  620.             dprintf(notrace,    "Assertion \"%s\" Failed\n"                    \
  621.                                     "Exception \"%s\" Raised\n"                    \
  622.                                     "File: %s\n"                                        \
  623.                                     "Line: %d",                                            \
  624.                 #assertion, #exception, __FILE__, __LINE__);                    \
  625.             goto exception;                                                            \
  626.             resumeLabel(exception);                                                    \
  627.         }                                                                                    \
  628.     } while (false)
  629.  
  630. #else
  631.  
  632. #define require(assertion, exception)                                            \
  633.     do {                                                                                    \
  634.         if (assertion) ;                                                                \
  635.         else {                                                                            \
  636.             goto exception;                                                            \
  637.             resumeLabel(exception);                                                    \
  638.         }                                                                                    \
  639.     } while (false)
  640.  
  641. #endif
  642.  
  643. /*<FF>*/
  644. /*********************************************************************
  645.  
  646. MACRO
  647.     nrequire(assertion, exception)
  648.  
  649. DESCRIPTION
  650.     nrequire will test !assertion and if it fails:
  651.         break into the debugger if debugging is on.
  652.         goto exception.
  653.  
  654. *********************************************************************/
  655.  
  656. #if    __DEBUGSMALL
  657.  
  658. #define nrequire(assertion, exception)                                            \
  659.     do {                                                                                    \
  660.         if (assertion) {                                                                \
  661.             DebugStr();                                                                    \
  662.             goto exception;                                                            \
  663.             resumeLabel(exception);                                                    \
  664.         }                                                                                    \
  665.     } while (false)
  666.  
  667. #elif    DEBUGLEVEL == DEBUGON
  668.  
  669. #define nrequire(assertion, exception)                                            \
  670.     do {                                                                                    \
  671.         void*    __privateAssertion    = (void*)(assertion);                    \
  672.                                                                                             \
  673.         if (__privateAssertion) {                                                    \
  674.             dprintf(notrace,    "Assertion \"!(%s [= %#08X])\" Failed\n"    \
  675.                                     "Exception \"%s\" Raised",                        \
  676.                 #assertion, __privateAssertion, #exception);                    \
  677.             goto exception;                                                            \
  678.             resumeLabel(exception);                                                    \
  679.         }                                                                                    \
  680.     } while (false)
  681.  
  682. #elif DEBUGLEVEL == DEBUGFULL
  683.  
  684. #define nrequire(assertion, exception)                                            \
  685.     do {                                                                                    \
  686.         void*    __privateAssertion    = (void*)(assertion);                    \
  687.                                                                                             \
  688.         if (__privateAssertion) {                                                    \
  689.             dprintf(notrace,    "Assertion \"!(%s [= %#08X])\" Failed\n"    \
  690.                                     "Exception \"%s\" Raised\n"                    \
  691.                                     "File: %s\n"                                        \
  692.                                     "Line: %d",                                            \
  693.                 #assertion, __privateAssertion, #exception, __FILE__,        \
  694.                 __LINE__);                                                                \
  695.             goto exception;                                                            \
  696.             resumeLabel(exception);                                                    \
  697.         }                                                                                    \
  698.     } while (false)
  699.  
  700. #else
  701.  
  702. #define nrequire(assertion, exception)                                            \
  703.     do {                                                                                    \
  704.         if (assertion) {                                                                \
  705.             goto exception;                                                            \
  706.             resumeLabel(exception);                                                    \
  707.         }                                                                                    \
  708.     } while (false)
  709.  
  710. #endif
  711.  
  712. /*<FF>*/
  713. /*********************************************************************
  714.  
  715. MACRO
  716.     require_action(assertion, exception, action)
  717.  
  718. DESCRIPTION
  719.     require_action will test assertion and if it fails:
  720.         break into the debugger if debugging is on.
  721.         execute action.
  722.         goto exception.
  723.  
  724. *********************************************************************/
  725.  
  726. #if    __DEBUGSMALL
  727.  
  728. #define require_action(assertion, exception, action)                        \
  729.     do {                                                                                    \
  730.         if (assertion) ;                                                                \
  731.         else {                                                                            \
  732.             __DebuggerBreak;                                                            \
  733.             { action }                                                                    \
  734.             goto exception;                                                            \
  735.             resumeLabel(exception);                                                    \
  736.         }                                                                                    \
  737.     } while (false)
  738.  
  739. #elif    DEBUGLEVEL == DEBUGON
  740.  
  741. #define require_action(assertion, exception, action)                        \
  742.     do {                                                                                    \
  743.         if (assertion) ;                                                                \
  744.         else {                                                                            \
  745.             dprintf(notrace,    "Assertion \"%s\" Failed\n"                    \
  746.                                     "Exception \"%s\" Raised",                        \
  747.             #assertion, #exception);                                                \
  748.             { action }                                                                    \
  749.             goto exception;                                                            \
  750.             resumeLabel(exception);                                                    \
  751.         }                                                                                    \
  752.     } while (false)
  753.  
  754. #elif DEBUGLEVEL == DEBUGFULL
  755.  
  756. #define require_action(assertion, exception, action)                        \
  757.     do {                                                                                    \
  758.         if (assertion) ;                                                                \
  759.         else {                                                                            \
  760.             dprintf(notrace,    "Assertion \"%s\" Failed\n"                    \
  761.                                     "Exception \"%s\" Raised\n"                    \
  762.                                     "File: %s\n"                                        \
  763.                                     "Line: %d",                                            \
  764.                 #assertion, #exception, __FILE__, __LINE__);                    \
  765.             { action }                                                                    \
  766.             goto exception;                                                            \
  767.             resumeLabel(exception);                                                    \
  768.         }                                                                                    \
  769.     } while (false)
  770.  
  771. #else
  772.  
  773. #define require_action(assertion, exception, action)                        \
  774.     do {                                                                                    \
  775.         if (assertion) ;                                                                \
  776.         else {                                                                            \
  777.             { action }                                                                    \
  778.             goto exception;                                                            \
  779.             resumeLabel(exception);                                                    \
  780.         }                                                                                    \
  781.     } while (false)
  782.  
  783. #endif
  784.  
  785. /*<FF>*/
  786. /*********************************************************************
  787.  
  788. MACRO
  789.     nrequire_action(assertion, exception, action)
  790.  
  791. DESCRIPTION
  792.     nrequire_action will test !assertion and if it fails:
  793.         break into the debugger if debugging is on.
  794.         execute action.
  795.         goto exception.
  796.  
  797. *********************************************************************/
  798.  
  799. #if    __DEBUGSMALL
  800.  
  801. #define nrequire_action(assertion, exception, action)                        \
  802.     do {                                                                                    \
  803.         if (assertion) {                                                                \
  804.             __DebuggerBreak;                                                            \
  805.             { action }                                                                    \
  806.             goto exception;                                                            \
  807.             resumeLabel(exception);                                                    \
  808.         }                                                                                    \
  809.     } while (false)
  810.  
  811. #elif DEBUGLEVEL == DEBUGON
  812.  
  813. #define nrequire_action(assertion, exception, action)                        \
  814.     do {                                                                                    \
  815.         void*    __privateAssertion    = (void*)(assertion);                    \
  816.                                                                                             \
  817.         if (__privateAssertion) {                                                    \
  818.             dprintf(notrace,    "Assertion \"!(%s [= %#08X])\" Failed\n"    \
  819.                                     "Exception \"%s\" Raised",                        \
  820.                 #assertion, __privateAssertion, #exception);                    \
  821.             { action }                                                                    \
  822.             goto exception;                                                            \
  823.             resumeLabel(exception);                                                    \
  824.         }                                                                                    \
  825.     } while (false)
  826.  
  827. #elif DEBUGLEVEL == DEBUGFULL
  828.  
  829. #define nrequire_action(assertion, exception, action)                        \
  830.     do {                                                                                    \
  831.         void*    __privateAssertion    = (void*)(assertion);                    \
  832.                                                                                             \
  833.         if (__privateAssertion) {                                                    \
  834.             dprintf(notrace,    "Assertion \"!(%s [= %#08X])\" Failed\n"    \
  835.                                     "Exception \"%s\" Raised\n"                    \
  836.                                     "File: %s\n"                                        \
  837.                                     "Line: %d",                                            \
  838.                 #assertion, __privateAssertion, #exception, __FILE__,        \
  839.                 __LINE__);                                                                \
  840.             { action }                                                                    \
  841.             goto exception;                                                            \
  842.             resumeLabel(exception);                                                    \
  843.         }                                                                                    \
  844.     } while (false)
  845.  
  846. #else
  847.  
  848. #define nrequire_action(assertion, exception, action)                        \
  849.     do {                                                                                    \
  850.         if (assertion) {                                                                \
  851.             { action }                                                                    \
  852.             goto exception;                                                            \
  853.             resumeLabel(exception);                                                    \
  854.         }                                                                                    \
  855.     } while (false)
  856.  
  857. #endif
  858.     
  859. /*<FF>*/
  860. /*********************************************************************
  861.  
  862. MACRO
  863.     resume(exception)
  864.  
  865. DESCRIPTION
  866.     resume will resume execution after the n/require/_action statement
  867.     specified by exception. Resume lables must be on (the default) in
  868.     order to use resume. If an action form of require was used then the
  869.     action will not be re-executed.
  870.  
  871. *********************************************************************/
  872.  
  873.  
  874. #define resume(exception)                                                            \
  875.     do {                                                                                    \
  876.         goto resume_ ## exception;                                                    \
  877.     } while (false)
  878.  
  879.  
  880. /*<FF>*/
  881. /********************************************************************/
  882.  
  883. #endif